﻿(function ($) {
    var methods = {
        init: function (options, jsonData) {
            return this.each(function () {
                var settings = {
            };
            var $this = $(this),
                        data = $this.data('jupdater'),
                        jupdater = $('<div />', {
                    });

            // If the plugin hasn't been initialized yet
            if (!data) {
                if (options) {
                    $.extend(settings, options);
                }
                $(this).data('jupdater', {
                    target: $this,
                    jupdater: jupdater,
                    json: _setJSONObject(jsonData),
                    settings: settings,
                    errorContainer: _getErrorContainer($this)
                });
            };
            if (typeof settings.onGetSuccess === 'function') {
                $(this).bind('getSuccess.jupdater', settings.onGetSuccess);
            }
            if (typeof settings.onPostSuccess === 'function') {
                $(this).bind('postSuccess.jupdater', settings.onPostSuccess);
            }
            if (typeof settings.onGetError === 'function') {
                $(this).bind('getError.jupdater', settings.onGetError);
            }
            if (typeof settings.onPostError === 'function') {
                $(this).bind('postError.jupdater', settings.onPostError);
            }
            if (typeof settings.onComplete === 'function') {
                $(this).bind('complete.jupdater', settings.onComplete);
            }
            if (typeof settings.onBeginUpdate === 'function') {
                $(this).bind('beginUpdate.jupdater', settings.onBeginUpdate);
            }
            if (typeof settings.onError === 'function') {
                $(this).bind('error.jupdater', settings.onError);
            }

            if (settings.deferLoad === true && $(this).is(':visible') === true) {
                $(this).jupdater('refresh');
            }
        });
    },

    destroy: function () {
        return this.each(function () {
            var $this = $(this), data = $this.data('jupdater');

            $(window).unbind('.jupdater');
            data.jupdater.remove();
            $this.removeData('jupdater');
        })
    },

    refresh: function () {
        return this.each(function () {
            var canUpdate = _onBeginUpdate($(this));
            if (canUpdate == undefined || canUpdate == true) {
                _callPageMethod($(this), 'POST', 'Refresh', _getControlValues($(this)), _onGetSuccess, _onGetError);
            }
        });
    },

    refresh: function (sender) {
        return this.each(function () {
            var canUpdate = _onBeginUpdate($(this));
            if (canUpdate == undefined || canUpdate == true) {
                _callPageMethod($(this), 'POST', 'Refresh', _getControlValues($(this), sender), _onGetSuccess, _onGetError);
            }
        });
    },

    submit: function (sender) {
        return this.each(function () {
            var canSubmit = $(this).triggerHandler('submit');
            if (canSubmit == undefined || canSubmit == true) {
                canSubmit = _onBeginUpdate($(this));
                if (canSubmit == undefined || canSubmit == true) {
                    _callPageMethod($(this), 'POST', 'SetPostBackData', _getControlValues($(this), sender), _onPostSuccess, _onPostError);
                }
            }
        });
    },

    setParam: function (param) {
        return this.each(function () {
            var $this = $(this), data = $this.data('jupdater');
            $.extend(data.json, _setJSONObject(param));
        })
    }
};


$.fn.jupdater = function (method) {
    if (methods[method]) {
        return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
        return methods.init.apply(this, arguments);
    } else {
        $.error('Method ' + method + ' does not exist on jQuery.jupdater');
    }
};

function _getControlValues($context, sender) {
    var hashtable = {};
    var controls = $context.find('[meta=jControl]');
    if (controls.length > 0) {
        var value = null;
        var postType = null;
        var name = null;
        var skipFirstItem = null;
        controls.each(function () {
            postType = $(this).attr('post');
            name = $(this).attr('id');
            if (!name || name == '') {
                return true;
            }
            switch (postType) {
                case "value":
                    value = $(this).val();
                    hashtable[name] = value;
                    break;
                case "text":
                    value = $(this).text();
                    hashtable[name] = value;
                    break;
                case "textandvalue":
                    value = $(this).attr('jValue');
                    if (value && value != null && value != '') {
                        value = $.evalJSON(value);
                        hashtable[name] = value;
                    }
                    break;
                default:
                    value = eval($(this).val());
                    if (value) {
                        hashtable[name] = value;
                    }
                    break;
            }
            //jqgrid PageIndex
            var pageIndex = $(this).attr('pageIndex');
            if (pageIndex && pageIndex !== '') {
                hashtable[$(this).attr('id') + '_pageIndex'] = eval(pageIndex);
            }
            //sender
            if (sender !== undefined && (name == sender || $(this).attr('id') == sender)) {
                hashtable['sender'] = $(this).attr('id');
            }
        });
    }
    hashtable["target"] = $context.attr('id');
    return hashtable;
};

function _setJSONObject($text) {
    if ($text) {
        return $.evalJSON($text)
    }
    return null;
};

function _getJSONString($jsonObject) {
    if ($jsonObject) {
        return $.toJSON($jsonObject);
    }
    return null;
};

function _callPageMethod($context, $requstType, $methodName, $objectData, $onSuccess, $onFail) {
    var locSplit = window.location.href.split("?");
    var loc = (locSplit[0].substr(locSplit[0].length - 1, 1) == "/") ? locSplit[0] + "default.aspx" : locSplit[0];
    var cType = "application/json; charset=utf-8";
    var dType = "json";
    _progressBar($context, true);
    var data = $context.data('jupdater');
    $.ajax({
        type: $requstType,
        url: loc + "/" + $methodName + window.location.search,
        data: _getJSONString($.extend($objectData, data.json)),
        contentType: cType,
        dataType: dType,
        context: $context,
        success: $onSuccess,
        error: $onFail,
        complete: _onComplete
    });
};

function _onGetSuccess(data, textStatus, request) {
    if (!_isRedirect(data.d)) {
        $(this).html(data.d);
    }
    $(this).triggerHandler('getSuccess', [data, textStatus, request]);
};

function _onGetError(request, textStatus, errorThrown) {
    if (!_isRedirect(request.responseText)) {
        _showError($(this), request.responseText);
        $(this).triggerHandler('getError', [request, textStatus, errorThrown]);
        $(this).triggerHandler('error', [request, textStatus, errorThrown]);
    }
};

function _onPostSuccess(data, textStatus, request) {
    if (!_isRedirect(data.d)) {
        $(this).html(data.d);
    }

    $(this).triggerHandler('postSuccess', [data, textStatus, request]);
};

function _onPostError(request, textStatus, errorThrown) {
    if (!_isRedirect(request.responseText)) {
        _showError($(this), request.responseText);
        $(this).triggerHandler('postError', [request, textStatus, errorThrown]);
        $(this).triggerHandler('error', [request, textStatus, errorThrown]);
    }
};

function _onComplete(request, textStatus) {
    _progressBar($(this), false);
    if (!_isRedirect(request.responseText)) {
        _ensureChildren($(this));
        $(this).triggerHandler('complete', [request, textStatus]);
    }
    else {
        window.location = _redirectUrl(request.responseText);
    }
};

function _onBeginUpdate($context) {
    return $context.triggerHandler('beginUpdate');
};


function _redirectUrl(rawUrl) {
    var url = $.evalJSON(rawUrl);
    if (url.d) {
        var idx = url.d.indexOf('location=');
        if (idx === 0) {
            return url.d.substring(idx + 9);
        }
    }
    return null;
};

function _isRedirect(rawUrl) {
    var idx1 = rawUrl.indexOf('{"d":"location=');
    var idx2 = rawUrl.indexOf('location=');
    return idx1 === 0 || idx2 === 0;
};

function _progressBar($context, $show) {
    if ($show === true) {
        var progressBar = _getProgressBar($context);
        if (progressBar === null) {
            $context.block();
        }
        else {
            $context.block({ message: progressBar.html() });
        }
    }
    else {
        $context.unblock();
    }
};

function _getProgressBar($context) {
    var progressId = $context.attr('progressID');
    if (progressId && progressId !== '') {
        var progress = $('#' + progressId);
        if (progress.length > 0) {
            return progress.clone().appendTo('#' + $context.attr('id'));
        }
    }
    return null;
};

function _getErrorContainer($context) {
    var containerId = $context.attr('errorContainerID');
    if (containerId && containerId !== '') {
        var container = $('#' + containerId);
        if (container.length > 0) {
            return container;
        }
    }
    return null;
};

function _showError($context, $errorHtml) {
    var data = $context.data().jupdater;
    if (!data) {
        data = $context.jupdater().data().jupdater;
    }
    if (data) {
        var container = data.errorContainer;
        if (container !== null) {
            var $errorWindow = $(container).AeroWindow('show'), data = $errorWindow.data('AeroWindow');
            data.Updater.html($errorHtml);
        }
    }
};

function _ensureChildren($context) {
    var childUpdaters = $context.find('[behavior=updater]');
    if (childUpdaters.length > 0) {
        childUpdaters.each(function () {
            $('#' + this.id).jupdater(null, null);
        });
    }

};
})(jQuery);
